#pragma once

#include "stdafx.h"
using namespace std;

namespace myutil{
//typedef map<int, int> iiMap;
//typedef map<string, int> siMap;
//typedef map<int, string> isMap;
//typedef map<int, double> idMap;

typedef unordered_map<int, int> iiMap;
typedef unordered_map<string, int> siMap;
typedef unordered_map<int, string> isMap;
typedef unordered_map<int, double> idMap;

typedef pair<int, int> iiPair;
typedef pair<string, int> siPair;
typedef pair<int, string> isPair;


//some functions for std output
//=================================
/*
 * output all the elements in a container
 * param : c: the container; num_per_line: the num of elements per line; sp: a string, the sparator between two elements
 * */
template<class T>
void print(const T & c, const int num_per_line = 1, const int num = -1, const char * sp = " ");

///////////////////////////////////////////////////////////////////////////////

void pause(int n);

//read the data from file path to res_str
int readFile(const char * path, string & res_str);
//write the data to the file path, length is num (chars)
int writeFile(const string & data, const char * path);
int writeFile(const char * data, const char * path);
int writeFile(const char * data, const int num, const char * path);

#ifdef _WIN32_WINNT
void CodeConvert_Win(string & output, const char * input, unsigned int fromCodePage, unsigned int toCodePage );
#endif

string getMidStr(const string & str, const char * start, const char * end, int start_index = 0);
int splitString(const char * str, vector<string> & res, const char sp);

int runCommand(string & result, const char * cmd);

int getWebPage(string url, string & res_data, const int timeOut = 8);
int removeSpecificTag(const char **);
int removeHtmlTag(string & source);
int removeHtmlComment(string & source);
int removeHtmlJS(string & source);

template<class T1, class T2>
inline bool comp_pair_by_value(const pair<T1, T2> & p1, const pair<T1, T2> & p2);
template <class T1, class T2>
inline int sort_map_by_value(const map<T1, T2> & m, vector<pair<T1, T2> > & res);

template<class T>
double getCos(const vector<T> & first, const vector<T> & second);

//Object Serialization
template<class T>
void saveOjbect(const T & obj, const char * path, const bool isTextArchive = true);
template<class T>
void loadObject(T & obj, const char * path, const bool isTextArchive = true);

}
/*
 * enable cout<<pairObject
 * voerlaod the operator<<
 */
template<class T1, class T2>
inline ostream & operator<<(ostream & o, const pair<T1, T2> & p);

template<class T>
inline ostream & operator<<(ostream & o, const vector<T> & p);

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

template<class T1, class T2>
inline ostream & operator<<(ostream & o, const pair<T1, T2> & p)
{
	return o << p.first << " : " << p.second;
}

template<class T>
inline ostream & operator<<(ostream & o, const vector<T> & p)
{
	int i = 0;
	for(i = 0; i < p.size() - 1; i++)
	{
		o << p[i] << " ";
	}
	return o << p[i];
}

/*
 *compare two pair object by their value(the second element in the pair object)
 *
 */
template<class T1, class T2>
inline bool myutil::comp_pair_by_value(const pair<T1, T2> & p1, const pair<T1, T2> & p2)
{
	return p1.second < p2.second;
}

/*
 * sort a map by the value
 * the sort reslut is the vector res
 * */
template <class T1, class T2>
inline int myutil::sort_map_by_value(const map<T1, T2> & m, vector<pair<T1, T2> > & res)
{
	res.clear();
	res.assign(m.begin(), m.end());
	sort(res.begin(), res.end(), comp_pair_by_value<T1, T2>);
	return 0;
}


/**
* function: 返回两个向量的Cos相似度
* params:
* version: 1.0
* author: lujun
*/
template<class T>
double myutil::getCos(const vector<T> & first, const vector<T> & second)
{
	assert(first.size() == second.size());
	double result = 0;
	double firstSqrtSum = 0;
	double secondSqrtSum = 0;
	for(int i = 0; i < first.size(); i++)
	{
		result += (first[i] * second[i]);
		firstSqrtSum += (first[i] * first[i]);
		secondSqrtSum += (second[i] * second[i]);
	}
	if(firstSqrtSum != 0 && secondSqrtSum != 0)
	{
		return result / sqrt(firstSqrtSum) / sqrt(secondSqrtSum);
	}

	return 0.0;
}

//============================================================================================

template<class T>
void myutil::print(const T & c, const int num_per_line, const int num, const char * sp)
{
	int count = 1;
	for(typename T::const_iterator pos = c.begin(); pos != c.end(); ++pos)
	{
		if(count % num_per_line == 0)
		{
			cout << *pos << endl;
		}
		else
		{
			cout << *pos << sp;
		}

		if(num > 0 && count > num)
		{
			break;
		}

		++count;
	}
	cout << endl;
}


template<class T>
void myutil::saveOjbect(const T & obj, const char * path, const bool isTextArchive)
{
	if(isTextArchive)
	{
		std::ofstream ofs(path);
		boost::archive::text_oarchive oa(ofs);
		oa << obj;
	}
	else
	{
		std::ofstream ofs(path, ios::binary);
		boost::archive::binary_oarchive oa(ofs);
		oa << obj;
	}
}

template<class T>
void myutil::loadObject(T & obj, const char * path, const bool isTextArchive)
{
	if(isTextArchive)
	{
		std::ifstream ifs(path);
		boost::archive::text_iarchive ia(ifs);
		ia >> obj;
	}
	else
	{
		std::ifstream ifs(path, ios::binary);
		boost::archive::binary_iarchive ia(ifs);
		ia >> obj;
	}
}

